package com.dingreading.cloud.mall.util;

import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.mall.dto.*;
import com.dingreading.cloud.mall.entity.*;
import com.dingreading.cloud.mall.service.*;
import com.dingreading.cloud.mall.util.redis.RedisService;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
public class OrderFormV3Util {

    public static OrderFormV3Util util;

    @PostConstruct
    public void init() {
        util = this;
    }

    //    @Resource
//    private ShopCartService shopCartService;
    @Resource
    private ShopCartV5Service shopCartService;
    @Resource
    private GoodsTypeService goodsTypeService;
    @Resource
    private GoodsService goodsService;
    @Resource
    private WhStockInService stockInService;
    @Resource
    private FreeDeliveryService freeDeliveryService;
    @Resource
    private CouponStaffService couponStaffService;
    @Resource
    private StoreGoodsDiscountService storeGoodsDiscountService;
    @Resource
    private RedisService redisService;


    /**
     * 新建门店员工-订单操作记录
     */
    public static OrderFormLog newStaffLog(
            String code, String operatorUid, String operator, Integer status, String statusName, String remark
    ) {
        OrderFormLog log = new OrderFormLog();
        log.setCode(code);
        log.setStatus(status);
        log.setStatusName(statusName);
        log.setOperatorUid(operatorUid);
        log.setOperator(operator);
        log.setType(EnumType.OPERATOR.STAFF.getType());
        log.setRemark(remark);
        return log;
    }

    /**
     * 生成系统收支记录
     */
    public static BalanceLog newBalanceLog(
            OrderForm order, Integer income, Integer payOnline, Long operatorId, String operatorName,
            Integer payType, String tradeType, String tradeTypeName, String buyerId,
            String tradeNo, String payTime
    ) {
        BalanceLog log = new BalanceLog();
        log.setCode(KitUtil.getBalanceCode());
        log.setProjectType(order.getProjectType());
        log.setProjectName(order.getProjectName());
        log.setOrderCode(order.getCode());
        log.setStoreUid(order.getStoreUid());
        log.setStoreName(order.getStoreName());
        log.setStaffUid(order.getStaffUid());
        log.setStaffName(order.getStaffName());
        log.setPhone(order.getPhone());
        log.setMoney(order.getPayPrice());
        log.setIncome(income);
        log.setPayOnline(payOnline);
        // 支付信息
        log.setPayType(payType);
        log.setTradeType(tradeType);
        log.setTradeTypeName(tradeTypeName);
        log.setBuyerId(buyerId);
        log.setTradeNo(tradeNo);
        log.setPayTime(payTime);
        // 代金券信息
        if (order.getCouponStaffId() != null) {
            log.setCouponStaffId(order.getCouponStaffId());
            log.setCouponMoney(order.getCouponPrice());
        }
        log.setSource(1);
        log.setStatus(1);
        log.setOperatorId(operatorId);
        log.setOperator(operatorName);
        return log;
    }

    /**
     * 生成系统收支记录
     */
    public static BalanceLog newBalanceLog(
            CooperPayOrder order, Integer income, Integer payOnline, Long operatorId, String operatorName,
            Integer payType, String tradeType, String tradeTypeName, String buyerId,
            String tradeNo, String payTime, String remark
    ) {
        BalanceLog log = new BalanceLog();
        log.setCode(KitUtil.getBalanceCode());
        log.setProjectType(order.getProjectType());
        log.setProjectName(order.getProjectName());
        log.setOrderCode(order.getCode());
        log.setMoney(order.getPayPrice());
        log.setIncome(income);
        log.setPayOnline(payOnline);
        log.setRemark(remark);
        // 支付信息
        log.setPayType(payType);
        log.setTradeType(tradeType);
        log.setTradeTypeName(tradeTypeName);
        log.setBuyerId(buyerId);
        log.setTradeNo(tradeNo);
        log.setPayTime(payTime);

        log.setSource(1);
        log.setStatus(1);
        log.setOperatorId(operatorId);
        log.setOperator(operatorName);
        return log;
    }

    /**
     * 新建订单地址
     */
    public static DeliveryAddressDto getAddressDto(DeliveryAddress data) {
        DeliveryAddressDto dto = new DeliveryAddressDto();

        List<String> provinceList = new ArrayList<>();
        if (StringUtils.isNotBlank(data.getProvince()))
            provinceList.add(data.getProvince());
        if (StringUtils.isNotBlank(data.getCity()))
            provinceList.add(data.getCity());
        if (StringUtils.isNotBlank(data.getDistrict()))
            provinceList.add(data.getDistrict());
        dto.setProvinces(provinceList);
        dto.setProvinceCode(data.getProvinceCode());
        dto.setCityCode(data.getCityCode());
        dto.setDistrictCode(data.getDistrictCode());
        dto.setProvince(data.getProvince());
        dto.setCity(data.getCity());
        dto.setDistrict(data.getDistrict());

        dto.setId(data.getId());
        dto.setAddress(data.getAddress());
        dto.setName(data.getName());
        dto.setPhone(data.getPhone());
        dto.setStatus(data.getStatus());
        dto.setAddTime(data.getAddTime());
        dto.setEditTime(data.getEditTime());
        return dto;
    }

    /**
     * 新建收货地址
     */
    public static DeliveryAddress newDeliveryAddress(
            DeliveryAddress data, String storeUid, String staffUid, String name, String phone,
            Integer status, String address, String provincesCode, String province, String cityCode,
            String city, String districtCode, String district) {
        if (data.getId() == null || data.getId() == 0) {
            data.setStoreUid(storeUid);
            data.setStaffUid(staffUid);
            data.setStatus(1);
        }
        if (name != null)
            data.setName(name);
        if (phone != null)
            data.setPhone(phone);
        if (address != null)
            data.setAddress(address);
        data.setProvinceCode(provincesCode);
        data.setProvince(province);
        data.setCityCode(cityCode);
        data.setCity(city);
        data.setDistrictCode(districtCode);
        data.setDistrict(district);
        data.setProvinces(mergeProvinceCityDistrict(province, city, district));

        if (status != null)
            data.setStatus(status);
        return data;
    }

    private static String mergeProvinceCityDistrict(String province, String city, String district) {
        String msg = "";
        if (StringUtils.isNotBlank(province))
            msg += province;
        if (StringUtils.isNotBlank(city))
            msg += "-" + city;
        if (StringUtils.isNotBlank(district))
            msg += "-" + district;

        return msg;
    }

    /**
     * 生成系统收支记录
     */
    public static CouponStaffLog newCouponStaffLog(
            CouponStaff couponStaff, String code, double useMoney, double usableMoney
    ) {
        CouponStaffLog log = new CouponStaffLog();
        log.setStoreUid(couponStaff.getStoreUid());
        log.setStaffUid(couponStaff.getStaffUid());
        log.setStoreName(couponStaff.getStoreName());
        log.setFullName(couponStaff.getFullName());
        log.setCode(code);
        log.setCouponId(couponStaff.getCouponId());
        log.setCouponName(couponStaff.getCouponName());
        log.setCouponStaffId(couponStaff.getId());
        log.setCouponMoney(couponStaff.getCouponMoney());
        log.setBeforeUseMoney(usableMoney);
        log.setUseMoney(useMoney);
        log.setUsableMoney(DoubleUtil.sub(usableMoney, useMoney));
        log.setStatus(1);
        return log;
    }

    /**
     * 获取商品规格的真实可售数，库存数量减去待发货数量
     *
     * @param stockNum    库存数
     * @param waitSendNum 待出库数
     */
    public static int getGoodsTypeNum(Integer stockNum, int waitSendNum) {
        return NepUtil.nullToZero(stockNum) - NepUtil.nullToZero(waitSendNum);
    }

    /**
     * 创建订单时验证购物车商品是否有效
     */
    public static R<ShopCartCheckDto> verifyShopCartToOrder(
            List<ShopCart> shopCartList, String storeUid, String staffUid, boolean selfStore, boolean newOrder, Long couponStaffId
    ) {
        // 验证代金券
        R<ShopCouponDto> couponInfoR = getCouponInfo(storeUid, staffUid, couponStaffId);
        if (R.isError(couponInfoR)) {
            return R.fail(couponInfoR.getMsg());
        }
        ShopCouponDto shopCouponDto = couponInfoR.getData();

        // 组合商品购物车记录
        List<String> mainShopCartUids = new ArrayList<>();
        // 无效商品购物车记录
        List<String> errorShopCartList = new ArrayList<>();
        // 付款方式
        int paymentMethod = 1;
        // 合并同一种商品规格的购物车记录
        Table<Long, Long, ShopCart> mainShopCartTable = TreeBasedTable.create();
        // 正常商品+组合子商品的购买数量，排除组合商品（判断库存数量）
        Table<Long, Long, Integer> judgeStockNumTable = HashBasedTable.create();
        // 正常商品的购买数量，排除组合商品和组合子商品（判断起购数量和采购倍数）
        Map<Long, Integer> judgeBuyNumAndBuyTimesTable = new HashMap<>();
        // 商品和商品规格id集合
        Set<Long> goodsIds = new HashSet<>();
        Set<Long> goodsTypeIds = new HashSet<>();
        // 购物车商品重量(包括组合商品)
        double totalWeight = 0;
        // 商品总数(包括组合商品)
        int totalBuyNum = 0;
        // 组合商品的子购物车记录
        List<ShopCart> childShopCartList = new ArrayList<>();

        // 处理购物车记录
        for (ShopCart cart : shopCartList) {
            // 验证购物车记录
            judgeShopCart(errorShopCartList, selfStore, cart);
            // 加入组合购物车记录uid
            if (CollectionUtils.isEmpty(errorShopCartList)) {
                goodsIds.add(cart.getGoodsId());
                goodsTypeIds.add(cart.getGoodsTypeId());

                if (cart.getComboType().equals(0)) {
                    // 购物车商品重量
                    totalWeight = DoubleUtil.sum(totalWeight, NepUtil.nullToZero(cart.getTotalWeight()));
                    // 商品总数
                    totalBuyNum += cart.getBuyNum();
                } else {
                    // 获取组合商品uid集合
                    mainShopCartUids.add(cart.getUid());
                }

                // 包含有银行转账
                if (paymentMethod == 1 && cart.getPaymentMethod().equals(2))
                    paymentMethod = 2;

                // 初始化购物车记录table信息
                initShopCartTable(cart, mainShopCartTable, judgeStockNumTable, judgeBuyNumAndBuyTimesTable);
            }
        }
        if (CollectionUtils.isNotEmpty(errorShopCartList))
            return R.fail("商品已失效，请删除后重试！" + String.join(",", errorShopCartList));

        // 处理组合商品的子购物车记录
        if (CollectionUtils.isNotEmpty(mainShopCartUids)) {
            childShopCartList = util.shopCartService.childListByStoreUidAndStaffUidAndUidsAndCodeIsNull(storeUid, staffUid, mainShopCartUids);
            if (CollectionUtils.isEmpty(childShopCartList))
                return R.fail("组合商品的购物车记录获取失败");

            for (ShopCart cart : childShopCartList) {
                // 验证购物车记录
                judgeShopCart(errorShopCartList, selfStore, cart);
                // 将组合商品的子商品记录加入购物车集合处理
                if (CollectionUtils.isEmpty(errorShopCartList)) {
                    goodsIds.add(cart.getGoodsId());
                    goodsTypeIds.add(cart.getGoodsTypeId());

                    // 购物车商品重量
                    totalWeight = DoubleUtil.sum(totalWeight, NepUtil.nullToZero(cart.getTotalWeight()));
                    // 商品总数
                    totalBuyNum += cart.getBuyNum();

                    // 包含有银行转账
                    if (paymentMethod == 1 && cart.getPaymentMethod().equals(2))
                        paymentMethod = 2;

                    // 初始化购物车记录table信息
                    initShopCartTable(cart, null, judgeStockNumTable, judgeBuyNumAndBuyTimesTable);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(errorShopCartList))
            return R.fail("商品已失效，请删除后重试！" + String.join(",", errorShopCartList));

        if (mainShopCartTable.isEmpty() || judgeStockNumTable.isEmpty())
            return R.fail("购物车商品信息解析失败");

        // 获取商品和商品规格信息
        ArrayList<Long> goodsIdList = new ArrayList<>(goodsIds);
        List<Goods> goodsList = util.goodsService.listByIds(goodsIdList);
        Map<Long, Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));
        ArrayList<Long> goodsTypeIdList = new ArrayList<>(goodsTypeIds);
        List<GoodsType> goodsTypeList = util.goodsTypeService.listByIds(goodsTypeIdList);
        Map<Long, GoodsType> goodsTypeMap = goodsTypeList.stream().collect(Collectors.toMap(GoodsType::getId, Function.identity()));

        // 验证商品和商品规格是否下架
        String resultMsg = judgeGoodsAndGoodsType(goodsList, goodsTypeList);
        if (StringUtils.isNotBlank(resultMsg))
            return R.fail(resultMsg);

        // 验证正常商品的起购数量、采购倍数
        resultMsg = judgeShopCartTable(selfStore, newOrder, goodsMap, goodsTypeMap, mainShopCartTable, judgeBuyNumAndBuyTimesTable);
        if (StringUtils.isNotBlank(resultMsg))
            return R.fail(resultMsg);

        // 验证商品的可售库存和待发货数量
        resultMsg = judgeStockNumAndWaitSendNum(goodsTypeIdList, goodsMap, goodsTypeMap, judgeStockNumTable);
        if (StringUtils.isNotBlank(resultMsg))
            return R.fail(resultMsg);

        // 商品种类包含叮叮书籍，收款公司是叮叮文化，1.叮叮文化 2.叮叮书房
        int corpPay = getCorpPay(goodsList);

        Double discountRate = util.storeGoodsDiscountService.getDiscountRate(storeUid);

        // 获取购物车商品的下单信息
        ShopCartCheckDto dto = getShopCartPrice(
                newOrder, goodsMap, goodsTypeMap, mainShopCartTable,
                shopCouponDto.getCouponTypeId(), shopCouponDto.getCouponUsableMoney(), shopCouponDto.getCouponGoodsIdList(), discountRate
        );
        dto.setCouponStaffId(couponStaffId);
        dto.setCouponName(shopCouponDto.getCouponName());

        dto.setNum(totalBuyNum);
        dto.setTotalWeight(totalWeight);
        dto.setShopCartList(shopCartList);
        dto.setPaymentMethod(paymentMethod);
        dto.setPayCorp(corpPay);
        dto.setChildShopCartList(childShopCartList);
        dto.setGoodsTypeMap(goodsTypeMap);
        return R.ok(dto);
    }

    /**
     * 计算购物车商品的金额
     */
    private static ShopCartCheckDto getShopCartPrice(
            boolean newOrder, Map<Long, Goods> goodsMap, Map<Long, GoodsType> goodsTypeMap, Table<Long, Long, ShopCart> shopCartTable,
            Long couponTypeId, double couponUsableMoney, Set<Long> couponGoodsIdList, Double discountRate
    ) {
        // 订单原价总金额
        AtomicReference<Double> totalOriginalPrice = new AtomicReference<>(0d);
        // 代金券抵扣金额
        AtomicReference<Double> totalDeductionPrice = new AtomicReference<>(0d);
        // 折扣金额
        AtomicReference<Double> totalDiscountPrice = new AtomicReference<>(0d);
        AtomicReference<Double> couponUsablePrice = new AtomicReference<>(couponUsableMoney);

        // 商品打折状态
        boolean discountStatus = discountRate != null && discountRate > 0;

        // 更新购物车的相关金额信息
        List<UpdateShopCartVo> updatePriceList = new ArrayList<>();

        // 按originalPrice排序
        shopCartTable.cellSet().stream()
                .sorted(Comparator.comparing((Table.Cell<Long, Long, ShopCart> cell) -> cell.getValue().getOriginalPrice()).reversed()
                        .thenComparing(cell -> cell.getValue().getOriginalPrice())
                ).forEach(cell -> {
                    ShopCart cart = cell.getValue();
                    double cartDeductionPrice = 0;
                    double cartDiscountPrice = 0;
                    double cartPrice = cart.getPrice();
                    // 计算正常商品和组合商品的金额，排除组合子商品
                    if (cart.getMainComboType().equals(0) || (cart.getMainComboType().equals(1) && cart.getComboType().equals(1))) {
                        Long goodsTypeId = cell.getRowKey();
                        Long goodsId = cell.getColumnKey();
                        Goods goods = goodsMap.get(goodsId);
                        GoodsType goodsType = goodsTypeMap.get(goodsTypeId);

                        Double originalPrice = cart.getOriginalPrice();
                        Double price = cart.getPrice();
                        // 订单原价总金额
                        totalOriginalPrice.set(DoubleUtil.sum(totalOriginalPrice.get(), originalPrice));
                        // 计算可使用代金券的商品金额
                        if (goods.getCouponStatus() != null && goods.getCouponStatus().equals(1) && couponTypeId != 0) {
                            if (couponTypeId == 1 || couponTypeId == 2) {
                                // 满减或全额券
                                if (couponUsablePrice.get() > 0) {
                                    if (couponUsablePrice.get() >= price) {
                                        cartDeductionPrice = price;
                                        totalDeductionPrice.set(DoubleUtil.sum(totalDeductionPrice.get(), cartDeductionPrice));
                                        couponUsablePrice.set(DoubleUtil.sub(couponUsablePrice.get(), cartDeductionPrice));
                                    } else {
                                        cartDeductionPrice = couponUsablePrice.get();
                                        totalDeductionPrice.set(DoubleUtil.sum(totalDeductionPrice.get(), cartDeductionPrice));
                                        couponUsablePrice.set(0d);
                                    }
                                }
                                if (cart.getDiscountPrice() != null) {
                                    cartDiscountPrice = cart.getDiscountPrice();
                                    totalDiscountPrice.set(DoubleUtil.sum(totalDiscountPrice.get(), cartDiscountPrice));
                                }
                            } else if (couponTypeId == 3) {
                                if (couponGoodsIdList.contains(goodsId)) {
                                    // 商品抵扣券，先抵扣原价再打折
                                    if (couponUsablePrice.get() > 0) {
                                        if (couponUsablePrice.get() >= originalPrice) {
                                            cartDeductionPrice = originalPrice;
                                            totalDeductionPrice.set(DoubleUtil.sum(totalDeductionPrice.get(), cartDeductionPrice));
                                            couponUsablePrice.set(DoubleUtil.sub(couponUsablePrice.get(), cartDeductionPrice));
                                        } else {
                                            cartDeductionPrice = couponUsablePrice.get();
                                            totalDeductionPrice.set(DoubleUtil.sum(totalDeductionPrice.get(), cartDeductionPrice));
                                            double subPrice = DoubleUtil.sub(originalPrice, cartDeductionPrice);
                                            if (discountStatus && goodsType.getDiscountStatus() != null && goodsType.getDiscountStatus().equals(1)) {
                                                double subDiscountPrice = DoubleUtil.mul(subPrice, discountRate);
                                                cartPrice = subDiscountPrice;
                                                cart.setPrice(cartPrice);
                                                cartDiscountPrice = DoubleUtil.sub(subPrice, subDiscountPrice);
                                            }
                                            couponUsablePrice.set(0d);
                                        }
                                    }
                                    totalDiscountPrice.set(DoubleUtil.sum(totalDiscountPrice.get(), cartDiscountPrice));
                                } else {
                                    if (cart.getDiscountPrice() != null) {
                                        cartDiscountPrice = cart.getDiscountPrice();
                                        totalDiscountPrice.set(DoubleUtil.sum(totalDiscountPrice.get(), cart.getDiscountPrice()));
                                    }
                                }
                            }
                        } else {
                            if (cart.getDiscountPrice() != null) {
                                cartDiscountPrice = cart.getDiscountPrice();
                                totalDiscountPrice.set(DoubleUtil.sum(totalDiscountPrice.get(), cart.getDiscountPrice()));
                            }
                        }
                    }

                    if (newOrder) {
                        UpdateShopCartVo cartPriceVo = new UpdateShopCartVo();
                        cartPriceVo.setUid(cart.getUid());
                        cartPriceVo.setDeductionPrice(cartDeductionPrice);
                        cartPriceVo.setDiscountPrice(cartDiscountPrice);
                        cartPriceVo.setPrice(cartPrice);
                        updatePriceList.add(cartPriceVo);
                    }
                });

        ShopCartCheckDto dto = new ShopCartCheckDto();
        dto.setOriginalPrice(totalOriginalPrice.get());
        dto.setDiscountPrice(totalDiscountPrice.get());
        dto.setDeductionPrice(totalDeductionPrice.get());
        double price = DoubleUtil.sub(totalOriginalPrice.get(), totalDiscountPrice.get());
        dto.setPrice(price);
        if (couponTypeId != null) {
            double payPrice = DoubleUtil.sub(price, totalDeductionPrice.get());
            dto.setPayPrice(payPrice);
        } else {
            dto.setPayPrice(price);
        }
        dto.setUpdatePriceList(updatePriceList);

        return dto;
    }

    /**
     * 验证购物车商品能否重新加入购物车
     */
    public static String verifyAgainAddShopCarts(
            boolean selfStore,
            boolean newOrder,
            List<ShopCart> mainAndChildCartList,
            Map<Long, Goods> goodsMap,
            Map<Long, GoodsType> goodsTypeMap,
            List<Long> goodsTypeIdList
    ) {
        // 无效商品购物车记录
        List<String> errorShopCartList = new ArrayList<>();
        // 付款方式
        // 合并同一种商品规格的购物车记录
        Table<Long, Long, ShopCart> shopCartTable = HashBasedTable.create();
        // 正常商品+组合子商品的购买数量，排除组合商品（判断库存数量）
        Table<Long, Long, Integer> judgeStockNumTable = HashBasedTable.create();
        // 正常商品的购买数量，排除组合商品和组合子商品（判断起购数量和采购倍数）
        Map<Long, Integer> judgeBuyNumAndBuyTimesTable = new HashMap<>();

        // 处理购物车记录
        for (ShopCart cart : mainAndChildCartList) {
            // 验证购物车记录
            judgeAgainAddShopCart(errorShopCartList, selfStore, cart);
            // 加入组合购物车记录uid
            if (CollectionUtils.isEmpty(errorShopCartList)) {
                // 初始化购物车记录table信息
                initShopCartTable(cart, shopCartTable, judgeStockNumTable, judgeBuyNumAndBuyTimesTable);
            }
        }
        if (CollectionUtils.isNotEmpty(errorShopCartList))
            return "商品已失效，不能操作" + String.join(",", errorShopCartList);

        if (shopCartTable.isEmpty() || judgeStockNumTable.isEmpty())
            return "购物车商品信息解析失败";

        // 验证正常商品的起购数量、采购倍数
        String resultMsg = judgeShopCartTable(selfStore, newOrder, goodsMap, goodsTypeMap, shopCartTable, judgeBuyNumAndBuyTimesTable);
        if (StringUtils.isNotBlank(resultMsg))
            return resultMsg;

        // 验证商品的可售库存和待发货数量
        resultMsg = judgeStockNumAndWaitSendNum(goodsTypeIdList, goodsMap, goodsTypeMap, judgeStockNumTable);
        if (StringUtils.isNotBlank(resultMsg))
            return resultMsg;

        return "";
    }


    /**
     * 验证商品订单是否有效
     */
    public static String verifyOrderForm(OrderForm form, boolean payPriceGtZero, boolean selfStore) {
        if (form.getProjectType() == null)
            return "订单类型未获取到";

        Double payPrice = NepUtil.nullToZero(form.getPayPrice());
        if (payPriceGtZero) {
            if (payPrice <= 0)
                return "订单支付金额必须大于0";
        } else {
            if (payPrice != 0)
                return "订单支付金额必须为0";
        }

        String code = form.getCode();
        if (form.getProjectType().equals(EnumType.BalanceProject.BUY_GOODS.getType())) {
            if (selfStore) {
                // 不是自营门店订单且待确认，则失败
                if (!form.getPayChannelCode().equals(EnumType.PayChannelCode.SELF.getType()) || !form.getStatus().equals(EnumType.OrderForm.WAIT_CONFIRM.getType()))
                    return "赠品订单状态错误！订单状态：" + EnumType.OrderForm.getStatus(form.getStatus());
            } else {
                // 不是待支付且不是银行转账，则失败
                if (!form.getStatus().equals(EnumType.OrderForm.WAIT_PAY.getType())
                        && !(form.getPayChannelCode().equals(EnumType.PayChannelCode.BANK.getType()) && form.getStatus().equals(EnumType.OrderForm.APPLY_BANKPAY.getType())))
                    return "商城订单状态错误！订单状态：" + EnumType.OrderForm.getStatus(form.getStatus());
            }
        } else if (form.getProjectType().equals(EnumType.BalanceProject.GIFT_GOODS.getType())) {
            // 不是赠品订单且待确认，则失败
            if (!form.getPayChannelCode().equals(EnumType.PayChannelCode.GIFT.getType()) || !form.getStatus().equals(EnumType.OrderForm.WAIT_CONFIRM.getType()))
                return "赠品订单状态错误！订单状态：" + EnumType.OrderForm.getStatus(form.getStatus());
        } else {
            return "订单类型错误！" + form.getProjectName();
        }

        // 获取购物车和自购物车记录
        List<ShopCart> mainAndChildCartList = util.shopCartService.mainListAndChildListByCode(code);
        if (CollectionUtils.isEmpty(mainAndChildCartList))
            return "未获取到订单的购物车记录";

        // 无效商品购物车记录
        List<String> errorShopCartList = new ArrayList<>();
        // 合并同一种商品规格的购物车记录
        Table<Long, Long, ShopCart> shopCartTable = HashBasedTable.create();
        // 正常商品+组合子商品的购买数量，排除组合商品（判断库存数量）
        Table<Long, Long, Integer> judgeStockNumTable = HashBasedTable.create();
        // 正常商品的购买数量，排除组合商品和组合子商品（判断起购数量和采购倍数）
        Map<Long, Integer> judgeBuyNumAndBuyTimesTable = new HashMap<>();
        // 商品和商品规格id集合
        Set<Long> goodsIds = new HashSet<>();
        Set<Long> goodsTypeIds = new HashSet<>();
        int totalBuyNum = 0;
        // 处理购物车记录
        for (ShopCart cart : mainAndChildCartList) {
            if (form.getProjectType().equals(EnumType.BalanceProject.BUY_GOODS.getType()))
                judgeOrderFormShopCart(errorShopCartList, selfStore, cart);
            else if (form.getProjectType().equals(EnumType.BalanceProject.GIFT_GOODS.getType()))
                judgeGiftOrderFormShopCart(errorShopCartList, selfStore, cart);
            // 加入组合购物车记录uid
            if (CollectionUtils.isEmpty(errorShopCartList)) {
                goodsIds.add(cart.getGoodsId());
                goodsTypeIds.add(cart.getGoodsTypeId());
                // 初始化购物车记录table信息
                initShopCartTable(cart, shopCartTable, judgeStockNumTable, judgeBuyNumAndBuyTimesTable);
                // 计算正常商品和组合商品的金额和购买数，排除组合子商品
                if (cart.getComboType().equals(0)) {
                    totalBuyNum += cart.getBuyNum();
                }
            }
        }

        if (CollectionUtils.isNotEmpty(errorShopCartList))
            return "订单内商品已失效，请重新下单";
        if (!form.getBuyNum().equals(totalBuyNum))
            return "购买数量不一致，请重新下单";
        double totalPrice = DoubleUtil.sub(DoubleUtil.sub(form.getPrice(), NepUtil.nullToZero(form.getDiscountPrice())), NepUtil.nullToZero(form.getCouponPrice()));
        if (!form.getPayPrice().equals(totalPrice))
            return "订单金额不一致，请重新下单";

        // 获取商品和商品规格信息
        ArrayList<Long> goodsIdList = new ArrayList<>(goodsIds);
        List<Goods> goodsList = util.goodsService.listByIds(goodsIdList);
        Map<Long, Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));
        ArrayList<Long> goodsTypeIdList = new ArrayList<>(goodsTypeIds);
        List<GoodsType> goodsTypeList = util.goodsTypeService.listByIds(goodsTypeIdList);
        Map<Long, GoodsType> goodsTypeMap = goodsTypeList.stream().collect(Collectors.toMap(GoodsType::getId, Function.identity()));

        // 验证商品和商品规格是否下架
        String resultMsg = judgeGoodsAndGoodsType(goodsList, goodsTypeList);
        if (StringUtils.isNotBlank(resultMsg))
            return resultMsg;

        // 验证正常商品的起购数量、采购倍数
        resultMsg = judgeShopCartTable(selfStore, true, goodsMap, goodsTypeMap, shopCartTable, judgeBuyNumAndBuyTimesTable);
        if (StringUtils.isNotBlank(resultMsg))
            return resultMsg;

        // 验证商品的可售库存数
        resultMsg = judgeStockNum(goodsTypeIdList, goodsMap, goodsTypeMap, judgeStockNumTable);
        if (StringUtils.isNotBlank(resultMsg))
            return resultMsg;

        return "";
    }

    /**
     * 商品种类包含叮叮书籍，收款公司是叮叮文化，1.叮叮文化 2.叮叮书房
     */
    private static int getCorpPay(List<Goods> goodsList) {
//        int corpPay = 2;
//        for (Goods goods : goodsList) {
//            if (goods.getCategoryIds().contains(",7,")) {
//                corpPay = 1;
//                break;
//            }
//        }
//        return corpPay;
        return 1;
    }

    /**
     * 判断商品和商品规格是否下架
     */
    private static String judgeGoodsAndGoodsType(List<Goods> goodsList, List<GoodsType> goodsTypeList) {
        Set<String> goodsNames = new HashSet<>();
        for (Goods goods : goodsList) {
            if (goods.getEnabled().equals(0))
                goodsNames.add(goods.getName());
        }
        if (CollectionUtils.isEmpty(goodsNames)) {
            for (GoodsType goodsType : goodsTypeList) {
                if (goodsType.getEnabled().equals(0))
                    goodsNames.add(goodsType.getName());
            }
            if (CollectionUtils.isNotEmpty(goodsNames))
                return "商品规格已下架！" + String.join(",", goodsNames);
        } else {
            return "商品已下架！" + String.join(",", goodsNames);
        }
        return "";
    }

    /**
     * 验证购物车记录
     */
    private static void judgeShopCart(List<String> errorShopCartList, boolean selfStore, ShopCart cart) {
        if (null != cart.getCode()) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!cart.getStatus().equals(EnumType.ShopCart.WAIT_CONFIRM.getType())) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (null == cart.getPaymentMethod() || (!cart.getPaymentMethod().equals(1) && !cart.getPaymentMethod().equals(2))) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getBuyNum() <= 0 || cart.getPrice() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getFreeDeliveryId() == null || cart.getFreeDeliveryId() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getComboType().equals(0) && cart.getStockOutMethod() == null) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!selfStore && cart.getMainComboType().equals(0) && cart.getBuyNum() < cart.getMinBuyNum()) {
            // 非自营门店且正常商品，判断购买数量不能低于最少购买数
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        }
    }

    /**
     * 验证购物车记录
     */
    private static void judgeAgainAddShopCart(List<String> errorShopCartList, boolean selfStore, ShopCart cart) {
        if (null != cart.getCode()) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!cart.getStatus().equals(EnumType.ShopCart.WAIT_CONFIRM.getType())) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (null == cart.getPaymentMethod() || (!cart.getPaymentMethod().equals(1) && !cart.getPaymentMethod().equals(2))) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getBuyNum() <= 0 || cart.getPrice() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getComboType().equals(0) && cart.getStockOutMethod() == null) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!selfStore && cart.getMainComboType().equals(0) && cart.getBuyNum() < cart.getMinBuyNum()) {
            // 非自营门店且正常商品，判断购买数量不能低于最少购买数
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        }
    }

    /**
     * 验证恢复购物车记录
     */
    private static void judgeResumeShopCart(List<String> errorShopCartList, boolean selfStore, ShopCart cart) {
        if (null == cart.getCode()) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!cart.getStatus().equals(EnumType.ShopCart.CANCEL.getType())) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (null == cart.getPaymentMethod() || (!cart.getPaymentMethod().equals(1) && !cart.getPaymentMethod().equals(2))) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getBuyNum() <= 0 || cart.getPrice() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getFreeDeliveryId() == null || cart.getFreeDeliveryId() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getComboType().equals(0) && cart.getStockOutMethod() == null) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!selfStore && cart.getMainComboType().equals(0) && cart.getBuyNum() < cart.getMinBuyNum()) {
            // 非自营门店且正常商品，判断购买数量不能低于最少购买数
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        }
    }

    /**
     * 验证商城订单的购物车记录
     */
    private static void judgeOrderFormShopCart(List<String> errorShopCartList, boolean selfStore, ShopCart cart) {
        if (null == cart.getCode()) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (null == cart.getPaymentMethod() || (!cart.getPaymentMethod().equals(1) && !cart.getPaymentMethod().equals(2))) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getBuyNum() <= 0 || cart.getPrice() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getFreeDeliveryId() == null || cart.getFreeDeliveryId() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getComboType().equals(0) && cart.getStockOutMethod() == null) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else {
            if (selfStore) {
                // 自营门店且不是待确认状态
                if (!cart.getStatus().equals(EnumType.ShopCart.WAIT_CONFIRM.getType()))
                    errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
            } else {
                // 非自营门店且不是待付款状态
                if (!cart.getStatus().equals(EnumType.ShopCart.WAIT_PAY.getType()))
                    errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
                // 非自营门店且正常商品，判断购买数量不能低于最少购买数
                if (cart.getMainComboType().equals(0) && cart.getBuyNum() < cart.getMinBuyNum())
                    errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
            }
        }
    }

    /**
     * 验证商城订单的购物车记录
     */
    private static void judgeGiftOrderFormShopCart(List<String> errorShopCartList, boolean selfStore, ShopCart cart) {
        if (null == cart.getCode()) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!cart.getStatus().equals(EnumType.ShopCart.WAIT_CONFIRM.getType())) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (null == cart.getPaymentMethod() || (!cart.getPaymentMethod().equals(1) && !cart.getPaymentMethod().equals(2))) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getBuyNum() <= 0 || cart.getPrice() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getFreeDeliveryId() == null || cart.getFreeDeliveryId() <= 0) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (cart.getComboType().equals(0) && cart.getStockOutMethod() == null) {
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        } else if (!selfStore && cart.getMainComboType().equals(0) && cart.getBuyNum() < cart.getMinBuyNum()) {
            // 非自营门店且正常商品，判断购买数量不能低于最少购买数
            errorShopCartList.add(getGoodsName(cart.getGoodsName(), cart.getGoodsTypeName()));
        }
    }

    private static String getGoodsName(String goodsName, String goodsTypeName) {
        return goodsName + "/" + goodsTypeName;
    }

    /**
     * 初始化购物车记录table信息
     */
    private static void initShopCartTable(
            ShopCart cart,
            Table<Long, Long, ShopCart> mainShopCartTable,
            Table<Long, Long, Integer> judgeStockNumTable,
            Map<Long, Integer> judgeBuyNumAndBuyTimesTable
    ) {
        Long goodsTypeId = cart.getGoodsTypeId();
        Long goodsId = cart.getGoodsId();

        if (mainShopCartTable != null) {
            // 只加入父购物车记录，排除组合子购物车记录
            if (cart.getMainComboType().equals(0) || (cart.getComboType().equals(1) && cart.getMainComboType().equals(1))) {
                mainShopCartTable.put(goodsTypeId, goodsId, cart);
            }
        }

        if (cart.getComboType().equals(0)) {
            Integer num = judgeStockNumTable.get(goodsTypeId, goodsId);
            judgeStockNumTable.put(goodsTypeId, goodsId, NepUtil.nullToZero(num) + cart.getBuyNum());

            if (cart.getMainComboType().equals(0)) {
                Integer num2 = NepUtil.nullToZero(judgeBuyNumAndBuyTimesTable.get(goodsId));
                judgeBuyNumAndBuyTimesTable.put(goodsId, num2 + cart.getBuyNum());
            }
        }


    }

    /**
     * 验证正常商品的起购数量、采购倍数、库存数量
     */
    private static String judgeShopCartTable(
            boolean selfStore,
            boolean newOrder,
            Map<Long, Goods> goodsMap,
            Map<Long, GoodsType> goodsTypeMap,
            Table<Long, Long, ShopCart> shopCartTable,
            Map<Long, Integer> judgeBuyNumAndBuyTimesTable
    ) {
        List<String> errorShopCartList = new ArrayList<>();
        // 判断购物车商品和商品规格是否存在
        for (Table.Cell<Long, Long, ShopCart> cell : shopCartTable.cellSet()) {
            GoodsType goodsType = goodsTypeMap.get(cell.getRowKey());
            Goods goods = goodsMap.get(cell.getColumnKey());
            if (goods == null || goodsType == null) {
                // 商品和商品规格不存在或已下架
                ShopCart cart = cell.getValue();
                errorShopCartList.add(cart.getGoodsName() + "/" + cart.getGoodsTypeName());
            }
        }
        if (CollectionUtils.isNotEmpty(errorShopCartList))
            return "商品已失效，请删除后重试！" + String.join(",", errorShopCartList);

        // 非自营门店，验证正常商品的起购数量和采购倍数
        if (!selfStore && newOrder && !judgeBuyNumAndBuyTimesTable.isEmpty()) {
            for (Map.Entry<Long, Integer> entry : judgeBuyNumAndBuyTimesTable.entrySet()) {
                Long goodsId = entry.getKey();
                // 商品规格的总购买数
                Integer buyCnt = entry.getValue();

                Goods goods = goodsMap.get(goodsId);
                // 商品的起购数量
                Integer minBuyCnt = NepUtil.nullToZero(goods.getMinBuyCnt());
                // 商品的采购倍数
                Integer buyTimes = NepUtil.nullToZero(goods.getBuyTimes());
                // 计算商品id相同的采购倍数
                int i = buyCnt % buyTimes;

                if (buyCnt < minBuyCnt && i != 0) {
                    return goods.getName() + "的总购买数是：" + buyCnt + "，没有达到起购数量：" + minBuyCnt + "，也没有达到采购倍数：" + buyTimes;
                } else if (buyCnt < minBuyCnt) {
                    return goods.getName() + "的总购买数是：" + buyCnt + "，没有达到起购数量：" + minBuyCnt;
                } else if (i != 0) {
                    return goods.getName() + "的总购买数是：" + buyCnt + "，没有达到采购倍数：" + buyTimes;
                }
            }
        }

        return "";
    }

    /**
     * 判断商品的可售库存和待发货库存
     */
    private static String judgeStockNumAndWaitSendNum(
            List<Long> goodsTypeIds,
            Map<Long, Goods> goodsMap,
            Map<Long, GoodsType> goodsTypeMap,
            Table<Long, Long, Integer> judgeStockNumTable
    ) {
        List<String> errorShopCartList = new ArrayList<>();

        // 根据购买记录和出库记录获取商品规格的待出库数量集合
        Map<Long, Integer> waitSendNumMap = util.shopCartService.getWaitSendNum(goodsTypeIds);
        // 获取商品的库存数量
        Map<Long, Integer> stockNumMap = util.stockInService.getStockNumMap(goodsTypeIds);
        // 判断商品购买数有没有超过库存数量
        for (Table.Cell<Long, Long, Integer> cell : judgeStockNumTable.cellSet()) {
            Long goodsTypeId = cell.getRowKey();
            Long goodsId = cell.getColumnKey();
            Integer buyNum = cell.getValue();
            // 真实库存数量
            int stockNum = getGoodsTypeNum(stockNumMap.get(goodsTypeId), waitSendNumMap.get(goodsTypeId));
            if (buyNum > stockNum) {
                Goods goods = goodsMap.get(goodsId);
                GoodsType goodsType = goodsTypeMap.get(goodsTypeId);
                errorShopCartList.add(goods.getName() + "/" + goodsType.getName() + " 库存：" + stockNum);
            }
        }
        if (CollectionUtils.isNotEmpty(errorShopCartList))
            return "商品库存数量不足！" + String.join(",", errorShopCartList);

        return "";
    }

    /**
     * 判断商品的可售库存和待发货库存
     */
    private static String judgeStockNum(
            List<Long> goodsTypeIds,
            Map<Long, Goods> goodsMap,
            Map<Long, GoodsType> goodsTypeMap,
            Table<Long, Long, Integer> judgeStockNumTable
    ) {
        List<String> errorShopCartList = new ArrayList<>();

        // 获取商品的库存数量
        Map<Long, Integer> stockNumMap = util.stockInService.getStockNumMap(goodsTypeIds);
        // 判断商品购买数有没有超过库存数量
        for (Table.Cell<Long, Long, Integer> cell : judgeStockNumTable.cellSet()) {
            Long goodsTypeId = cell.getRowKey();
            Long goodsId = cell.getColumnKey();
            Integer buyNum = cell.getValue();
            // 真实库存数量
            int stockNum = stockNumMap.get(goodsTypeId);
            if (buyNum > stockNum) {
                Goods goods = goodsMap.get(goodsId);
                GoodsType goodsType = goodsTypeMap.get(goodsTypeId);
                errorShopCartList.add(goods.getName() + "/" + goodsType.getName() + " 库存：" + stockNum);
            }
        }
        if (CollectionUtils.isNotEmpty(errorShopCartList))
            return "商品库存数量不足！" + String.join(",", errorShopCartList);

        return "";
    }


    /**
     * 判断商品和商品规格状态
     */
    public static String judgeGoodsAndGoodsType(
            boolean selfStatus, Integer mainComboType, Goods goods, GoodsType goodsType, int buyNum, Integer stockNum, Integer waitSendNUm
    ) {
        if (null == goods)
            return "商品获取失败";
        if (null == goodsType)
            return "商品规格获取失败";
        if (!goods.getEnabled().equals(1))
            return "商品已下架";
        if (!goodsType.getEnabled().equals(1))
            return "商品规格已下架";

        if (goods.getFreeDeliveryId() == null || goods.getFreeDeliveryId() <= 0)
            return "商品未设置包邮模板";
        if (null == goods.getPaymentMethod())
            return "商品的付款方式未设置";
        if (null == goodsType.getStockOutMethod())
            return "商品规格的出库方式未设置";
        if (mainComboType.equals(0)) {
            // 非自营门店且非组合商品，判断最低购买数
            if (!selfStatus && buyNum < goods.getMinBuyNum()) {
                return "购买数量不能低于最少购买数";
            }
        }
        // 获取商品规格的真实可售数，库存数量减去待发货数量
        int saleNum = OrderFormV3Util.getGoodsTypeNum(stockNum, waitSendNUm);
        if (buyNum > saleNum) {
            if (mainComboType.equals(0))
                return "购买数量不能超过库存数量！库存：" + saleNum;
            else
                return "商品库存数量不足，" + goods.getName() + "/" + goodsType.getName() + " 库存：" + saleNum;
        }
        return "";
    }

    /*---------------------------包邮规则-------------------------------*/

    /**
     * 购物车记录设置包邮规则
     */
    public static void setFreeDelivery(
            List<ShopCart> mainShopCartList, List<ShopCart> childShopCartList, Map<Long, GoodsType> goodsTypeMap,
            int selfStore, boolean newOrder, String storeProvince
    ) {
        // 先根据门店的省份判断是否参与包邮规则
        boolean addressLimit = freeDeliveryAddressLimit(storeProvince);
        if (addressLimit) {
            List<UpdateShopCartVo> updateList = new ArrayList<>();
            // 符合特殊省份不包邮
            for (ShopCart cart : mainShopCartList) {
                cart.setFreeDeliveryStatus(0);
                addUpdateShopCart(newOrder, updateList, cart.getUid(), cart.getFreeDeliveryId(), cart.getFreeDeliveryName(), cart.getFreeDeliveryStatus());
            }

            if (CollectionUtils.isNotEmpty(childShopCartList)) {
                for (ShopCart childCart : childShopCartList) {
                    childCart.setFreeDeliveryStatus(0);
                    addUpdateShopCart(newOrder, updateList, childCart.getUid(), childCart.getFreeDeliveryId(), childCart.getFreeDeliveryName(), childCart.getFreeDeliveryStatus());
                }
            }
            if (newOrder) {
                util.shopCartService.dbUpdateDeliveryStatus(updateList);
            }
            return;
        }

        if (selfStore == 1) {
            // 自营门店，默认包邮
            List<UpdateShopCartVo> updateList = new ArrayList<>();
            for (ShopCart cart : mainShopCartList) {
                cart.setFreeDeliveryStatus(1);
                addUpdateShopCart(newOrder, updateList, cart.getUid(), cart.getFreeDeliveryId(), cart.getFreeDeliveryName(), cart.getFreeDeliveryStatus());
            }

            if (CollectionUtils.isNotEmpty(childShopCartList)) {
                for (ShopCart childCart : childShopCartList) {
                    childCart.setFreeDeliveryStatus(1);
                    addUpdateShopCart(newOrder, updateList, childCart.getUid(), childCart.getFreeDeliveryId(), childCart.getFreeDeliveryName(), childCart.getFreeDeliveryStatus());
                }
            }
            if (newOrder) {
                util.shopCartService.dbUpdateDeliveryStatus(updateList);
            }
        } else if (selfStore == 3) {
            // 赠品订单，自定义是否包邮
            List<UpdateShopCartVo> updateList = new ArrayList<>();
            for (ShopCart cart : mainShopCartList) {
                addUpdateShopCart(newOrder, updateList, cart.getUid(), cart.getFreeDeliveryId(), cart.getFreeDeliveryName(), cart.getFreeDeliveryStatus());
            }

            if (CollectionUtils.isNotEmpty(childShopCartList)) {
                for (ShopCart childCart : childShopCartList) {
                    addUpdateShopCart(newOrder, updateList, childCart.getUid(), childCart.getFreeDeliveryId(), childCart.getFreeDeliveryName(), childCart.getFreeDeliveryStatus());
                }
            }
            if (newOrder) {
                util.shopCartService.dbUpdateDeliveryStatus(updateList);
            }

        } else {
            // 加盟店，判断是否包邮
            // 设置包邮的购物车记录，如果有套装且套装包邮即全部商品都包邮
            boolean allFreeDelivery = false;
            List<ShopCart> setDeliveryCartList = new ArrayList<>();
            Map<String, List<ShopCart>> childCartMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(childShopCartList))
                childCartMap = childShopCartList.stream().collect(Collectors.groupingBy(ShopCart::getMainShopCartUid));

            for (ShopCart cart : mainShopCartList) {
                if (cart.getMainComboType().equals(0) && cart.getComboType().equals(0)) {
                    // 普通商品
                    setDeliveryCartList.add(cart);
                } else if (cart.getMainComboType().equals(1) && cart.getComboType().equals(1)) {
                    // 组合商品，只对其内的子商品处理
                    List<ShopCart> childList = childCartMap.get(cart.getUid());
                    if (CollectionUtils.isNotEmpty(childList)) {
                        GoodsType goodsType = goodsTypeMap.get(cart.getGoodsTypeId());
                        // 套裝能否包邮状态
                        if (goodsType.getFreeDeliveryStatus().equals(0)) {
                            // 套装不包邮，以商品的包邮模板为准
                            setDeliveryCartList.addAll(childList);
                        } else {
                            // 如果有套装且套装包邮即全部商品都包邮
                            allFreeDelivery = true;
                            break;
                        }
                    }
                }
            }

            List<UpdateShopCartVo> updateList = new ArrayList<>();
            if (allFreeDelivery) {
                // 如果有套装且套装包邮即全部商品都包邮
                for (ShopCart cart : mainShopCartList) {
                    cart.setFreeDeliveryStatus(1);
                    addUpdateShopCart(newOrder, updateList, cart.getUid(), cart.getFreeDeliveryId(), cart.getFreeDeliveryName(), cart.getFreeDeliveryStatus());
                }
                if (!childCartMap.isEmpty()) {
                    childCartMap.values().stream().flatMap(List::stream)
                            .forEach(childCart -> {
                                childCart.setFreeDeliveryStatus(1);
                                addUpdateShopCart(newOrder, updateList, childCart.getUid(), childCart.getFreeDeliveryId(), childCart.getFreeDeliveryName(), childCart.getFreeDeliveryStatus());
                            });
                }
            } else {
                // 包邮处理后的购物车记录
                Map<String, Integer> dealCartMap = new HashMap<>();
                // 设置包邮的购物车记录
                if (CollectionUtils.isNotEmpty(setDeliveryCartList)) {
                    // 购物车记录按包邮模板id分组
                    Map<Long, List<ShopCart>> setDeliverCartMap = setDeliveryCartList.stream()
                            .collect(Collectors.groupingBy(ShopCart::getFreeDeliveryId));
                    // 获取包邮模板信息
                    List<FreeDelivery> freeDeliveryList = util.freeDeliveryService.listByIds(setDeliverCartMap.keySet());
                    Map<Long, FreeDelivery> freeDeliveryMap = freeDeliveryList.stream()
                            .collect(Collectors.toMap(FreeDelivery::getId, Function.identity()));
                    // 按包邮模板对商品进行包邮处理
                    for (Map.Entry<Long, List<ShopCart>> entry : setDeliverCartMap.entrySet()) {
                        Long freeDeliveryId = entry.getKey();
                        List<ShopCart> cartList = entry.getValue();

                        FreeDelivery freeDelivery = freeDeliveryMap.get(freeDeliveryId);
                        if (freeDelivery != null && freeDelivery.getType() != null) {
                            Integer type = freeDelivery.getType();
                            if (type.equals(1)) {
                                // 包邮
                                dealFreeDelivery(cartList);
                            } else if (type.equals(2)) {
                                // 满金额包邮
                                dealFreeDeliveryAmount(freeDelivery.getFreeAmount(), cartList);
                            } else if (type.equals(3)) {
                                // 满数量包邮
                                dealFreeDeliveryNum(freeDelivery.getFreeNum(), cartList);
                            } else {
                                // 邮费到付，默认不包邮
                            }
                        }
                    }

                    dealCartMap = setDeliverCartMap.values().stream()
                            .flatMap(List::stream)
                            .collect(Collectors.toList())
                            .stream()
                            .collect(Collectors.toMap(ShopCart::getUid, ShopCart::getFreeDeliveryStatus));
                }

                for (ShopCart cart : mainShopCartList) {
                    if (cart.getMainComboType().equals(0) && cart.getComboType().equals(0)) {
                        // 普通商品
                        Integer freeDeliveryStatus = dealCartMap.get(cart.getUid());
                        if (freeDeliveryStatus != null) {
                            cart.setFreeDeliveryStatus(freeDeliveryStatus);
                            addUpdateShopCart(newOrder, updateList, cart.getUid(), cart.getFreeDeliveryId(), cart.getFreeDeliveryName(), cart.getFreeDeliveryStatus());
                        }
                    } else if (cart.getMainComboType().equals(1) && cart.getComboType().equals(1)) {
                        List<ShopCart> childList = childCartMap.get(cart.getUid());
                        int mainFreeDeliveryStatus = 1;
                        if (CollectionUtils.isNotEmpty(childList)) {
                            // 组合商品，只对其内的子商品处理
                            GoodsType goodsType = goodsTypeMap.get(cart.getGoodsTypeId());
                            // 套裝能否包邮状态
                            if (goodsType.getFreeDeliveryStatus().equals(0)) {
                                // 套装不包邮，以商品的包邮模板为准
                                for (ShopCart childCart : childList) {
                                    Integer freeDeliveryStatus = dealCartMap.get(childCart.getUid());
                                    if (freeDeliveryStatus != null && freeDeliveryStatus.equals(1)) {
                                        childCart.setFreeDeliveryStatus(1);
                                        addUpdateShopCart(newOrder, updateList, childCart.getUid(), childCart.getFreeDeliveryId(), childCart.getFreeDeliveryName(), childCart.getFreeDeliveryStatus());
                                    } else {
                                        // 只要有一个子商品不包邮，组合商品就不包邮
                                        mainFreeDeliveryStatus = 0;
                                    }
                                }
                            }
                        }
                        cart.setFreeDeliveryStatus(mainFreeDeliveryStatus);
                        addUpdateShopCart(newOrder, updateList, cart.getUid(), cart.getFreeDeliveryId(), cart.getFreeDeliveryName(), cart.getFreeDeliveryStatus());
                    }
                }
            }

            // 创建订单时，购物车记录更新包邮状态
            if (newOrder) {
                util.shopCartService.dbUpdateDeliveryStatus(updateList);
            }
        }
    }

    /**
     * 创建更新购物车商品的对象
     */
    private static void addUpdateShopCart(
            boolean newOrder, List<UpdateShopCartVo> updateList, String cartUid, Long deliveryId, String deliveryName, Integer deliveryStatus
    ) {
        if (newOrder)
            updateList.add(new UpdateShopCartVo(cartUid, deliveryId, deliveryName, deliveryStatus));
    }

    /**
     * 包邮处理
     */
    private static void dealFreeDelivery(List<ShopCart> cartList) {
        for (ShopCart cart : cartList) {
            cart.setFreeDeliveryStatus(1);
        }
    }

    /**
     * 满金额包邮处理
     */
    private static void dealFreeDeliveryAmount(double freeAmount, List<ShopCart> cartList) {
        // 加盟店，商品总金额达到包邮金额包邮
        double amount = 0;
        for (ShopCart cart : cartList) {
            double price = NepUtil.nullToZero(cart.getPrice());
            amount = DoubleUtil.sum(amount, price);
        }

        int freeDeliveryStatus = amount >= freeAmount ? 1 : 0;

        // 购物车记录设置包邮状态
        for (ShopCart cart : cartList) {
            cart.setFreeDeliveryStatus(freeDeliveryStatus);
        }
    }

    /**
     * 满数量包邮处理
     */
    private static void dealFreeDeliveryNum(int freeNum, List<ShopCart> cartList) {
        // 加盟店，商品总数量达到包邮数量包邮
        int buyNum = 0;
        for (ShopCart cart : cartList) {
            buyNum += cart.getBuyNum();
        }

        int freeDeliveryStatus = buyNum >= freeNum ? 1 : 0;

        // 购物车记录设置包邮状态
        for (ShopCart cart : cartList) {
            cart.setFreeDeliveryStatus(freeDeliveryStatus);
        }
    }

    /**
     * 根据门店省份判断是否参与包邮规则
     */
    public static boolean freeDeliveryAddressLimit(String province) {
        if (province.contains("新疆") || province.contains("西藏") || province.contains("内蒙古")) {
            return true;
        }
        return false;
    }

    /**
     * 验证代金券
     */
    private static R<ShopCouponDto> getCouponInfo(String storeUid, String staffUid, Long couponStaffId) {
        ShopCouponDto shopCouponDto = new ShopCouponDto();
        if (couponStaffId != null && couponStaffId > 0) {
            CouponStaffDto couponStaff = util.couponStaffService.dtoGetStaffCoupon(storeUid, staffUid, couponStaffId);
            if (couponStaff == null) {
                return R.fail("未查询到代金券信息");
            }
            String couponName = couponStaff.getCouponName();
            double couponUsableMoney = NepUtil.nullToZero(couponStaff.getUsableMoney());
            if (couponUsableMoney <= 0)
                return R.fail("代金券的可用金额必须大于0");

            long couponTypeId = NepUtil.nullToZero(couponStaff.getTypeId());
            Set<Long> couponGoodsIdList = new HashSet<>();
            if (couponTypeId == 3) {
                String goodsIds = couponStaff.getGoodsIds();
                String goodsCategoryIds = couponStaff.getGoodsCategoryIds();
                if (StringUtils.isBlank(goodsIds) && StringUtils.isBlank(goodsCategoryIds)) {
                    return R.fail("代金券可抵扣的商品或商品分类不存在");
                }
                if (StringUtils.isNotBlank(goodsIds)) {
                    List<Long> goodsIdList = Arrays.stream(StringUtils.split(goodsIds, ","))
                            .map(Long::parseLong)
                            .collect(Collectors.toList());
                    couponGoodsIdList.addAll(goodsIdList);
                }
                if (StringUtils.isNotBlank(goodsCategoryIds)) {
                    Set<String> categoryIds = Arrays.stream(StringUtils.split(goodsCategoryIds, ","))
                            .collect(Collectors.toSet());
                    // 通过商品分类id查询商品id集合
                    if (CollectionUtils.isNotEmpty(categoryIds)) {
                        List<Long> goodsIdList = util.goodsService.idListByCategoryIdIn(categoryIds);
                        if (CollectionUtils.isNotEmpty(goodsIdList)) {
                            couponGoodsIdList.addAll(goodsIdList);
                        }
                    }
                }
            }

            shopCouponDto.setCouponTypeId(couponTypeId);
            shopCouponDto.setCouponName(couponName);
            shopCouponDto.setCouponUsableMoney(couponUsableMoney);
            shopCouponDto.setCouponGoodsIdList(couponGoodsIdList);
        }
        return R.ok(shopCouponDto);
    }
    /*----------------------------------------------------------------*/


    // 商城订单自动取消时间：3天
    public static final int mallExpireTime = 7 * 24 * 60 * 60;

    /**
     * 未支付的商城订单，1小时后进入redis过期回调
     */
    public static void addMallCodeToRedisExpire(String code) {
        util.redisService.set(RedisParam.MALL_CODE.concat(code), "", mallExpireTime);
    }

    /**
     * 删除redis过期自动取消的商城订单号
     */
    public static void deleteMallCodeFromRedisExpire(String code) {
        util.redisService.delete(RedisParam.MALL_CODE.concat(code));
    }

}
